﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Research.TouchMouseSensor;
using System.Windows;
using System.Windows.Forms;
using System.Drawing;

namespace IntelliTouchMix
{/*
    class BlobControler
    {
        // The current blobs being analized
        Blobs[] blobs;
        CircularIndex current_blob_index;
        // The window of blobs
        Blobs[][] blobs_buffer;
        public int iblob;
        public BlobControler(int n)
        {
            current_blob_index = new CircularIndex(1);
            current_blob_index.value = 0;
            int n_blobs_buffer = 2;
            blobs_buffer = new Blobs[n_blobs_buffer][];
            // Inicialize Blobs buffer
            for (int i = 0; i < n_blobs_buffer; ++i)
            {
                blobs_buffer[i] = new Blobs[n];
                // Inicialze individual blobs
                for (int j = 0; j < n; ++j)
                    blobs_buffer[i][j] = new Blobs();
            } 
        }
        public Blobs[] find(Byte[] img, int w, int h)
        {
            int i, size;
            if (img != null)
            {
                blobs = blobs_buffer[current_blob_index.next];
                // blobs = blobs_buffer[0];
                
                Blobs.setParams(img, w, h);
                iblob = 0;
                size = w * h;
                for (i = 0; i < size; ++i)
                {
                    // Find a lid pixel
                    if (img[i] > Blobs.threshold)
                    {
                        try
                        {
                            blobs[iblob].Clean();
                            blobs[iblob].expand(i);
                            blobs[iblob].normalize();
                            iblob++;
                        }
                        catch (Exception ex)
                        {
                            MessageBox.Show("value "+i+" \n"+ex.Message);
                        }
                        
                    }
                }
            }
            return blobs;
        }
    }
  * */
    class Blobs
    {
        public static int threshold = 50;
    
        public static byte[] img;
        public static int w, h;
        public static int eventLife;
        Point2f center, centroid;
        // Point2f center, centroid;
        Point2i max,min;
        int maxPixel;
        float avg;
        int nPixels;
        public bool isAnalized;
        float radius;
        int life;
        public Point2f getPos() { return centroid; }
        public static void setParams(TouchMouseSensorEventArgs e)
        {
            w = e.Status.m_dwImageWidth;
            h = e.Status.m_dwImageHeight;
            img = e.Image;
            eventLife = e.Status.m_dwTimeDelta;
        }
        public static void setParams(byte[]image,int width,int height){
            img = image;
            w = width;
            h = height;
        }

        public static PointF[] toPointF(Blobs[] v)
        {
            PointF[] f = new PointF[v.Length];
            for (int i = 0; i < v.Length; ++i)
            {
                f[i].X = v[i].centroid.x;
                f[i].Y = v[i].centroid.y;
            }
            return (PointF[])f;
        }
        public Blobs()
        {
            maxPixel = 0;
            radius = 0;
            centroid = new Point2f(0.0f, 0.0f);
            center = new Point2f(0.0f, 0.0f);
            min = new Point2i(50,50);
            max = new Point2i(0,0);
            avg = 0;
            isAnalized = false;
            nPixels = 0;
            life = 0;
        }
        public void set(Blobs b)
        {
            maxPixel = b.maxPixel;
            radius = b.radius;
            centroid = new Point2f(b.centroid.x,b.centroid.y);
            center = new Point2f(b.center.x, b.center.y);
            min = new Point2i(b.min.x, b.min.y);
            isAnalized = b.isAnalized;
            max = new Point2i(b.max.x, b.max.y);
            avg = b.avg;
            nPixels = b.nPixels;
            life = b.life;
        }
        public Blobs(Blobs b)
        {
            maxPixel = b.maxPixel;
            radius = b.radius;
            centroid = b.centroid;
            center = new Point2f(b.center.x, b.center.y);
            min = new Point2i(b.min.x, b.min.y);
            isAnalized = b.isAnalized;
            max = new Point2i(b.max.x, b.max.y);
            avg = b.avg;
            nPixels = b.nPixels;
            life = b.life;
        }
        public bool col(Blobs b)
        {
            Point2f d = centroid.sub(b.centroid);
            return (d.dist2() < b.radius+radius);
        }
        public float dist(Blobs b)
        {
            return b.centroid.dist2(centroid);
        }
        public int getTime(){
            return life;
        }
        public void addTime(Blobs b)
        {
            life += b.life;
        }
        public void Clean()
        {
            isAnalized = false;
            maxPixel = 0;
            avg = 0;
            nPixels = 0;
            min.set(w,h);
            max.set(0, 0);
            life = 0;
        }
        public int getMaxPixel()
        {
            return maxPixel;
        }
        public override String ToString()
        {
            String s = "Centroid: " + centroid + "\n";
            s += "Center: " + center + "\n";
            s += "avg: " + avg + "\n";
            s += "max: " + max + "\n";
            s += "min: " + min + "\n";
            s += "nPixels: " + nPixels + "\n";
            s += "radious: " + radius + "\n";
            s += "maxPixel: " + maxPixel + "\n";
            s += "Time: " + life + "\n";
            // if (avg > 100 && maxPixel > 120)
            //if (avg > 125 && maxPixel > 150)
           // if (avg > 100 && maxPixel > 140)
            if(maxPixel > 140)
            {
                s += "skin\n";
            }
            else if(maxPixel> 90)
                s += "hair\n";
            else //if (maxPixel > 110)
                s += "paper\n";
            return s;
        }

        void calculate(int i){
            int x = i%w;
            int y = i/w;
            // get max and min
            maxPixel =  Math.Max(img[i], maxPixel);
            max.max(x, y);
            min.min(x, y);
            // sum
            avg += img[i];
            centroid.add(x*img[i],y*img[i]);
            nPixels++;
        }
        public void normalize(){
            int dx,dy;
            center.x = (max.x + min.x) / 2.0f;
            center.y = (max.y + min.y) / 2.0f;
            dx=max.x-min.x;
            dy=max.y-min.y;
            radius = dx * dx + dy * dy;
            centroid.normalize(avg);
            avg /= nPixels;
            life = eventLife;
        }
        public void normalize(int count)
        {
            centroid.normalize(count);
            center.normalize(count);
            nPixels /= count;
            maxPixel = (int)((float)maxPixel/count);
            avg /= (float)count;
        }
        public int getNPixels() { return nPixels; }
        public void add(Blobs b)
        {
            this.centroid.add(b.centroid);
            this.center.add(b.center);
            this.nPixels += b.nPixels;
            this.maxPixel += b.maxPixel;
            this.avg += b.avg;
        }
        public void expand(int i){
            // Calculations
            calculate(i);
            // turn of the pixel
            img[i] = 0;
            int n = w*h;
            // expand the pixel, search the neighbours
            if (i + 1 < n)
            {
                if (img[i + 1] > threshold)
                    expand(i + 1);
                if (i+w<n && img[i + w] > threshold)
                    expand(i + w);
            }
            if (i - 1 >= 0)
            {
                if (img[i - 1] > threshold)
                    expand(i - 1);
                if (i - w > 0 && img[i - w] > threshold)
                    expand(i - w);
            }
           
        }

       
        
    }
}
